package com.sky.service.impl;

import com.github.pagehelper.Constant;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.entity.Setmeal;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;


@Service
@Slf4j
public class DishServiceImpl implements DishService {
    // 注入Mapper层对象
    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private DishFlavorMapper dishFlavorMapper;
    @Autowired
    private SetmealDishMapper setmealDishMapper;
    @Autowired
    private SetmealMapper setmealMapper;

    @Transactional // 开启注解事务管理
    /*新增菜品方法*/
    @Override
    public void saveWithFlavor(DishDTO dishDTO) {
        // 1. 向菜品表插入1条数据
        Dish dish = new Dish();
        // 拷贝属性
        BeanUtils.copyProperties(dishDTO, dish);
        // 调用mapper层方法
        dishMapper.insert(dish);
        // 获取主键
        Long dishId = dish.getId();
        // 2. 向口味表中插入多条数据
        List<DishFlavor> flavorList = dishDTO.getFlavors();
        // 判断口味是否传递数据
        if (flavorList == null || flavorList.size() == 0) {
            return; // 结束方法
        }
        // 将每一个口味的菜品id设置为当前菜品的id
        flavorList.forEach(dishFlavor -> {
            dishFlavor.setDishId(dishId);
        });
        // 如果口味不为空,调用mapper方法插入数据
        dishFlavorMapper.insertBatch(flavorList);
    }

    @Override
    public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
        // 使用分页查询插件
        PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
        // 调用mapper层方法
        Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);
        return new PageResult(page.getTotal(), page.getResult());
    }

    @Override
    public void deleteByIds(List<Long> ids) {
        /**
         * 删除规则：
         *  业务规则：
         * 可以一次删除一个菜品，也可以批量删除菜品
         * 起售中的菜品不能删除
         * 被套餐关联的菜品不能删除
         * 删除菜品后，关联的口味数据也需要删除掉
         * */
        // 1.判断菜品是否可以删除，判断是否存在 启用的菜品
        for (Long id : ids) {
            Dish dish = dishMapper.getById(id);
            if (dish.getStatus().equals(StatusConstant.ENABLE)) {
                // 当前菜品是启用状态，不能删除
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);// 菜品处于销售中，不能删除
            }
        }
        // 2.判断菜品是否有套餐包含， 注意处理逻辑，是根据菜品id才套餐菜品关联表中查，如果有查到，则不能删除
        List<Long> setMealIds = setmealDishMapper.getSetmealIdsByDishIds(ids);
        if (setMealIds.size() > 0) {
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL); // 菜品被套餐关联，不能删除
        }
        // 3.删除菜品，再删除菜品口味， dishId = id;
       /* for (Long id : ids) {
            dishMapper.deleteById(id);
            // 删除菜品关联的口味数据
            dishFlavorMapper.deleteByDishId(id);
        }*/
        // 改进版
        //1.根据菜品ids集合删除菜品数据
        dishMapper.deleteByIds(ids);
        //2.根据菜品ids集合删除菜品口味数据
        dishFlavorMapper.deleteByDishIds(ids);

    }

    /*根据id查询菜品信息*/
    @Override
    public DishVO getDishById(Long id) {
        //1.根据菜品id查询菜品基本信息
        Dish dish = dishMapper.getDishById(id);
        //2.根据菜品id查询分类信息
        List<DishFlavor> flavorList = dishFlavorMapper.getFlavorByDishId(id);
        //3.将查询到信息合并到VO对象中
        DishVO dishVO = new DishVO();
        BeanUtils.copyProperties(dish, dishVO);
        dishVO.setFlavors(flavorList);
        return dishVO;
    }

    /*根据id修改菜品信息，前端传递的是DTO对象*/
    @Override
    public void updateDishWithFlavor(DishDTO dishDTO) {
        /*
         * 分为两个步骤，先修改菜品基本信息，再修改菜品口味信息
         * */
        //1. 修改菜品基本信息
        Dish dish = new Dish();
        //2. 属性拷贝
        BeanUtils.copyProperties(dishDTO, dish);
        // 调用Mapper层方法修改新菜品信息
        dishMapper.update(dish);
        // 获取菜品id
        Long DishId = dishDTO.getId();
        //3. 修改菜品口味信息,先删除原来的所有口味，再添加现在的前端传递过来的菜品口味
        dishFlavorMapper.deleteByDishId(DishId);
        //4. 插入所有新的口味数据
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if (flavors.size() > 0) {
            flavors.forEach(dishFlavor -> {
                dishFlavor.setDishId(DishId); // 为每一个口味数据设置菜品id
            });
            // last.调用口味mapper层方法插入新的口味数据
            dishFlavorMapper.insertBatch(flavors);
        }

    }


    /*根据分类id查询菜品信息*/
    @Override
    public List<Dish> getByCategoryId(Long categoryId) {
        // 设置查询条件
        Dish dish = new Dish();
        dish.setCategoryId(categoryId);
        dish.setStatus(StatusConstant.ENABLE);
        // 调用Mapper层查询菜品
        List<Dish> dishList = dishMapper.getByCategoryId(dish);
        return dishList;
    }

    /*修改菜品状态*/
    @Override
    @Transactional// 添加到事务中，涉及到多个表的操作，所以需要添加事务
    public void enableOrBan(Integer status, Long id) {
        // 新建一个Dish对象，将状态值设置为status当前值，
        Dish dish = new Dish();
        dish.setStatus(status);
        dish.setId(id);
        // 调用Mapper层方法 修改菜品信息
        dishMapper.update(dish);
        // 如果菜品被禁用且包含在某个套餐中，则套餐的状态也需要修改为禁用
        if (status.equals(StatusConstant.DISABLE)) {
            // 当前是禁用操作,将菜品所在的套餐状态也同样修改为禁用
            List<Long> dishIds = new ArrayList<>(); // 新建一个菜品id的集合, 因为查询套餐的方法传递的参数是一个集合,所以即使当前操作的只是一个菜品id，那么也要创建集合装入其中
            dishIds.add(id);// 将当前的操作的菜品id添加到集合中
            // 根据菜品id集合查询套餐id集合
            List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(dishIds);
            // 将这些个套餐id的状态修改为禁用
            if (setmealIds.size() > 0) {
                setmealIds.forEach(setmealId -> {
                    // 如果有套餐包含当前被禁用的菜品，那么禁用当前的套餐
                    Setmeal setmeal = new Setmeal();
                    setmeal.setStatus(StatusConstant.DISABLE);
                    setmeal.setId(setmealId);
                    // 修改套餐状态
                    setmealMapper.update(setmeal);
                });
            }
        }
    }


    /*根据菜品id查询菜品的信息和口味信息
     * */
    @Override
    public List<DishVO> listWithFlavor(Dish dish) {
        List<Dish> dishList = dishMapper.getByCategoryId(dish);
        List<DishVO> dishVOList = new ArrayList<>();
        // 遍历菜品集合，拿出所有的菜品id，查询口味表
        for (Dish d : dishList) {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(d, dishVO);

            // 根据菜品id查询对应的口味表
            List<DishFlavor> flavors = dishFlavorMapper.getFlavorByDishId(d.getId());
            // 将口味数据添加到对应的DISHVO集合元素中
            dishVO.setFlavors(flavors);
            dishVOList.add(dishVO);
        }
        return dishVOList;
    }
}
